// #pragma once//防止被一个文件重复引用时重复展开
#if !defined(__RINGQUEUE_HPP__) //==//#ifndef __RINGQUEUE_HPP__
#define __RINGQUEUE_HPP__ 1

#include <iostream>
#include <vector>
#include <semaphore.h>

template <class T>
class RingQueue
{
private:
    void P(sem_t *p_sem)
    {
        sem_wait(p_sem);
    }
    void V(sem_t *v_sem)
    {
        sem_post(v_sem);
    }

public:
    RingQueue(int capacityMax)
        : _capacityMax(capacityMax), _ringqueue(capacityMax), _p_index(0), _c_index(0)
    {
        // 锁+信号量初始化
        pthread_mutex_init(&_c_mutex, nullptr);
        pthread_mutex_init(&_p_mutex, nullptr);
        sem_init(&_data_sem, 0, 0);
        sem_init(&_space_sem, 0, _capacityMax);
    }
    void Push(const T *in) // 入队列
    {
        P(&_space_sem);//放在临界区外，使临界区更短，串行执行时间更短，效率更高
        pthread_mutex_lock(&_p_mutex);
        _ringqueue[_p_index] = *in;
        _p_index++;
        _p_index %= _capacityMax; // 数组循环
        pthread_mutex_unlock(&_p_mutex);
        V(&_data_sem);
    }

    void Pop(T *out) // 获取数据后，出队列，
    {
        P(&_data_sem);
        pthread_mutex_lock(&_c_mutex);
        *out = _ringqueue[_c_index];
        _c_index++;               // 下一个消费的下标
        _c_index %= _capacityMax; // 数组循环
        pthread_mutex_unlock(&_c_mutex);
        V(&_space_sem);
    }

    ~RingQueue()
    {
        // 锁+信号量销毁
        pthread_mutex_destroy(&_c_mutex);
        pthread_mutex_destroy(&_p_mutex);
        sem_destroy(&_data_sem);
        sem_destroy(&_space_sem);
    }

private:
    std::vector<T> _ringqueue;
    // 信号量
    sem_t _data_sem;  // 消费者关心
    sem_t _space_sem; // 生产者关心
    // 下标
    int _p_index; // 下一个数据资源位置下标
    int _c_index;
    // 容量
    int _capacityMax;
    // 锁
    pthread_mutex_t _c_mutex;
    pthread_mutex_t _p_mutex;
};

#endif